"""
清洁标准管理器
负责管理和配置不同区域的清洁标准，提供清洁标准的CRUD操作
"""
import asyncio
import logging
import json
from datetime import datetime, timedelta
from typing import List, Dict, Optional, Any, Tuple
from uuid import uuid4
from pathlib import Path
from collections import defaultdict

from schemas.hygiene_management import (
    CleanlinessLevel, CleanlinessConfig, HygieneZone
)
from core.config import get_settings

logger = logging.getLogger(__name__)
settings = get_settings()


class CleanlinessStandard:
    """清洁标准模型"""
    
    def __init__(
        self,
        standard_id: str,
        name: str,
        description: str,
        zone_type: str,
        score_thresholds: Dict[str, Tuple[float, float]],
        weight_factors: Dict[str, float],
        cleaning_frequency: str,
        special_requirements: List[str] = None,
        created_at: datetime = None,
        updated_at: datetime = None
    ):
        self.standard_id = standard_id
        self.name = name
        self.description = description
        self.zone_type = zone_type
        self.score_thresholds = score_thresholds
        self.weight_factors = weight_factors
        self.cleaning_frequency = cleaning_frequency
        self.special_requirements = special_requirements or []
        self.created_at = created_at or datetime.now()
        self.updated_at = updated_at or datetime.now()
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            'standard_id': self.standard_id,
            'name': self.name,
            'description': self.description,
            'zone_type': self.zone_type,
            'score_thresholds': self.score_thresholds,
            'weight_factors': self.weight_factors,
            'cleaning_frequency': self.cleaning_frequency,
            'special_requirements': self.special_requirements,
            'created_at': self.created_at.isoformat(),
            'updated_at': self.updated_at.isoformat()
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'CleanlinessStandard':
        """从字典创建"""
        return cls(
            standard_id=data['standard_id'],
            name=data['name'],
            description=data['description'],
            zone_type=data['zone_type'],
            score_thresholds=data['score_thresholds'],
            weight_factors=data['weight_factors'],
            cleaning_frequency=data['cleaning_frequency'],
            special_requirements=data.get('special_requirements', []),
            created_at=datetime.fromisoformat(data['created_at']),
            updated_at=datetime.fromisoformat(data['updated_at'])
        )


class CleanlinessStandardsManager:
    """清洁标准管理器"""
    
    def __init__(self, standards_file: str = "data/cleanliness_standards.json"):
        self.standards_file = Path(standards_file)
        self.standards_file.parent.mkdir(parents=True, exist_ok=True)
        
        self.standards: Dict[str, CleanlinessStandard] = {}
        self.zone_standards: Dict[str, str] = {}  # zone_id -> standard_id
        
        # 加载标准
        self._load_standards()
        
        # 如果没有标准，创建默认标准
        if not self.standards:
            self._create_default_standards()
    
    def _load_standards(self):
        """加载清洁标准"""
        try:
            if self.standards_file.exists():
                with open(self.standards_file, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                
                # 加载标准
                for standard_data in data.get('standards', []):
                    standard = CleanlinessStandard.from_dict(standard_data)
                    self.standards[standard.standard_id] = standard
                
                # 加载区域标准映射
                self.zone_standards = data.get('zone_standards', {})
                
                logger.info(f"Loaded {len(self.standards)} cleanliness standards")
        
        except Exception as e:
            logger.error(f"Failed to load cleanliness standards: {e}")
    
    def _save_standards(self):
        """保存清洁标准"""
        try:
            data = {
                'standards': [standard.to_dict() for standard in self.standards.values()],
                'zone_standards': self.zone_standards,
                'updated_at': datetime.now().isoformat()
            }
            
            with open(self.standards_file, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
            
            logger.info("Cleanliness standards saved")
        
        except Exception as e:
            logger.error(f"Failed to save cleanliness standards: {e}")
    
    def _create_default_standards(self):
        """创建默认清洁标准"""
        # 教室标准
        classroom_standard = CleanlinessStandard(
            standard_id="classroom_standard",
            name="教室清洁标准",
            description="适用于普通教室的清洁标准",
            zone_type="classroom",
            score_thresholds={
                "excellent": (90, 100),
                "good": (80, 89),
                "fair": (70, 79),
                "poor": (60, 69),
                "very_poor": (0, 59)
            },
            weight_factors={
                "waste_presence": 0.35,
                "surface_cleanliness": 0.25,
                "organization": 0.20,
                "maintenance": 0.15,
                "lighting": 0.05
            },
            cleaning_frequency="daily",
            special_requirements=[
                "桌椅整齐摆放",
                "黑板清洁",
                "地面无垃圾",
                "窗户明亮"
            ]
        )
        
        # 走廊标准
        hallway_standard = CleanlinessStandard(
            standard_id="hallway_standard",
            name="走廊清洁标准",
            description="适用于走廊和过道的清洁标准",
            zone_type="hallway",
            score_thresholds={
                "excellent": (85, 100),
                "good": (75, 84),
                "fair": (65, 74),
                "poor": (55, 64),
                "very_poor": (0, 54)
            },
            weight_factors={
                "waste_presence": 0.40,
                "surface_cleanliness": 0.30,
                "organization": 0.10,
                "maintenance": 0.15,
                "lighting": 0.05
            },
            cleaning_frequency="twice_daily",
            special_requirements=[
                "地面清洁",
                "墙面无污渍",
                "照明充足",
                "通风良好"
            ]
        )
        
        # 洗手间标准
        restroom_standard = CleanlinessStandard(
            standard_id="restroom_standard",
            name="洗手间清洁标准",
            description="适用于洗手间的高标准清洁要求",
            zone_type="restroom",
            score_thresholds={
                "excellent": (95, 100),
                "good": (85, 94),
                "fair": (75, 84),
                "poor": (65, 74),
                "very_poor": (0, 64)
            },
            weight_factors={
                "waste_presence": 0.30,
                "surface_cleanliness": 0.35,
                "organization": 0.15,
                "maintenance": 0.15,
                "lighting": 0.05
            },
            cleaning_frequency="hourly",
            special_requirements=[
                "无异味",
                "设施完好",
                "消毒彻底",
                "纸巾充足",
                "地面干燥"
            ]
        )
        
        # 实验室标准
        laboratory_standard = CleanlinessStandard(
            standard_id="laboratory_standard",
            name="实验室清洁标准",
            description="适用于实验室的专业清洁标准",
            zone_type="laboratory",
            score_thresholds={
                "excellent": (92, 100),
                "good": (82, 91),
                "fair": (72, 81),
                "poor": (62, 71),
                "very_poor": (0, 61)
            },
            weight_factors={
                "waste_presence": 0.25,
                "surface_cleanliness": 0.30,
                "organization": 0.25,
                "maintenance": 0.15,
                "lighting": 0.05
            },
            cleaning_frequency="daily",
            special_requirements=[
                "实验台清洁",
                "设备整洁",
                "化学品安全存放",
                "通风系统正常",
                "废料分类处理"
            ]
        )
        
        # 办公室标准
        office_standard = CleanlinessStandard(
            standard_id="office_standard",
            name="办公室清洁标准",
            description="适用于办公室的清洁标准",
            zone_type="office",
            score_thresholds={
                "excellent": (88, 100),
                "good": (78, 87),
                "fair": (68, 77),
                "poor": (58, 67),
                "very_poor": (0, 57)
            },
            weight_factors={
                "waste_presence": 0.30,
                "surface_cleanliness": 0.25,
                "organization": 0.25,
                "maintenance": 0.15,
                "lighting": 0.05
            },
            cleaning_frequency="daily",
            special_requirements=[
                "桌面整洁",
                "文件有序",
                "设备清洁",
                "空气清新"
            ]
        )
        
        # 添加标准
        standards = [
            classroom_standard,
            hallway_standard,
            restroom_standard,
            laboratory_standard,
            office_standard
        ]
        
        for standard in standards:
            self.standards[standard.standard_id] = standard
        
        # 保存默认标准
        self._save_standards()
        
        logger.info("Created default cleanliness standards")
    
    def create_standard(self, standard: CleanlinessStandard) -> str:
        """创建清洁标准"""
        if standard.standard_id in self.standards:
            raise ValueError(f"Standard with ID {standard.standard_id} already exists")
        
        standard.created_at = datetime.now()
        standard.updated_at = datetime.now()
        
        self.standards[standard.standard_id] = standard
        self._save_standards()
        
        logger.info(f"Created cleanliness standard: {standard.standard_id}")
        return standard.standard_id
    
    def update_standard(self, standard_id: str, updates: Dict[str, Any]) -> bool:
        """更新清洁标准"""
        if standard_id not in self.standards:
            return False
        
        standard = self.standards[standard_id]
        
        # 更新字段
        for key, value in updates.items():
            if hasattr(standard, key):
                setattr(standard, key, value)
        
        standard.updated_at = datetime.now()
        
        self._save_standards()
        
        logger.info(f"Updated cleanliness standard: {standard_id}")
        return True
    
    def delete_standard(self, standard_id: str) -> bool:
        """删除清洁标准"""
        if standard_id not in self.standards:
            return False
        
        # 检查是否有区域在使用这个标准
        using_zones = [
            zone_id for zone_id, std_id in self.zone_standards.items()
            if std_id == standard_id
        ]
        
        if using_zones:
            raise ValueError(f"Cannot delete standard {standard_id}: used by zones {using_zones}")
        
        del self.standards[standard_id]
        self._save_standards()
        
        logger.info(f"Deleted cleanliness standard: {standard_id}")
        return True
    
    def get_standard(self, standard_id: str) -> Optional[CleanlinessStandard]:
        """获取清洁标准"""
        return self.standards.get(standard_id)
    
    def get_all_standards(self) -> List[CleanlinessStandard]:
        """获取所有清洁标准"""
        return list(self.standards.values())
    
    def get_standards_by_zone_type(self, zone_type: str) -> List[CleanlinessStandard]:
        """根据区域类型获取清洁标准"""
        return [
            standard for standard in self.standards.values()
            if standard.zone_type == zone_type
        ]
    
    def assign_standard_to_zone(self, zone_id: str, standard_id: str) -> bool:
        """为区域分配清洁标准"""
        if standard_id not in self.standards:
            return False
        
        self.zone_standards[zone_id] = standard_id
        self._save_standards()
        
        logger.info(f"Assigned standard {standard_id} to zone {zone_id}")
        return True
    
    def get_zone_standard(self, zone_id: str) -> Optional[CleanlinessStandard]:
        """获取区域的清洁标准"""
        standard_id = self.zone_standards.get(zone_id)
        if standard_id:
            return self.standards.get(standard_id)
        return None
    
    def get_zone_config(self, zone_id: str) -> CleanlinessConfig:
        """获取区域的清洁配置"""
        standard = self.get_zone_standard(zone_id)
        
        if standard:
            return CleanlinessConfig(
                assessment_method="comprehensive",
                weight_factors=standard.weight_factors,
                score_thresholds=standard.score_thresholds,
                enable_comparison=True,
                comparison_period_days=7
            )
        else:
            # 返回默认配置
            return CleanlinessConfig()
    
    def validate_standard(self, standard: CleanlinessStandard) -> List[str]:
        """验证清洁标准"""
        errors = []
        
        # 验证权重因子
        weight_sum = sum(standard.weight_factors.values())
        if abs(weight_sum - 1.0) > 0.01:
            errors.append(f"Weight factors sum to {weight_sum:.3f}, should be 1.0")
        
        # 验证评分阈值
        for level, (min_score, max_score) in standard.score_thresholds.items():
            if min_score < 0 or max_score > 100:
                errors.append(f"Score thresholds for {level} out of range [0, 100]")
            
            if min_score >= max_score:
                errors.append(f"Invalid score range for {level}: [{min_score}, {max_score}]")
        
        # 验证必需字段
        required_factors = ['waste_presence', 'surface_cleanliness', 'organization', 'maintenance']
        for factor in required_factors:
            if factor not in standard.weight_factors:
                errors.append(f"Missing required weight factor: {factor}")
        
        return errors
    
    def get_statistics(self) -> Dict[str, Any]:
        """获取统计信息"""
        zone_type_counts = defaultdict(int)
        for standard in self.standards.values():
            zone_type_counts[standard.zone_type] += 1
        
        return {
            'total_standards': len(self.standards),
            'zone_type_distribution': dict(zone_type_counts),
            'assigned_zones': len(self.zone_standards),
            'unassigned_zones': 0,  # 需要从区域服务获取
            'last_updated': max(
                (s.updated_at for s in self.standards.values()),
                default=datetime.now()
            ).isoformat()
        }
    
    def export_standards(self, file_path: str) -> bool:
        """导出清洁标准"""
        try:
            export_data = {
                'export_time': datetime.now().isoformat(),
                'standards': [standard.to_dict() for standard in self.standards.values()],
                'zone_assignments': self.zone_standards
            }
            
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(export_data, f, ensure_ascii=False, indent=2)
            
            logger.info(f"Exported cleanliness standards to {file_path}")
            return True
        
        except Exception as e:
            logger.error(f"Failed to export standards: {e}")
            return False
    
    def import_standards(self, file_path: str, overwrite: bool = False) -> Dict[str, Any]:
        """导入清洁标准"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                import_data = json.load(f)
            
            imported_count = 0
            skipped_count = 0
            error_count = 0
            
            for standard_data in import_data.get('standards', []):
                try:
                    standard = CleanlinessStandard.from_dict(standard_data)
                    
                    # 验证标准
                    errors = self.validate_standard(standard)
                    if errors:
                        logger.warning(f"Validation errors for standard {standard.standard_id}: {errors}")
                        error_count += 1
                        continue
                    
                    # 检查是否已存在
                    if standard.standard_id in self.standards and not overwrite:
                        skipped_count += 1
                        continue
                    
                    self.standards[standard.standard_id] = standard
                    imported_count += 1
                
                except Exception as e:
                    logger.error(f"Failed to import standard: {e}")
                    error_count += 1
            
            # 导入区域分配
            if 'zone_assignments' in import_data:
                for zone_id, standard_id in import_data['zone_assignments'].items():
                    if standard_id in self.standards:
                        self.zone_standards[zone_id] = standard_id
            
            # 保存更改
            if imported_count > 0:
                self._save_standards()
            
            result = {
                'imported': imported_count,
                'skipped': skipped_count,
                'errors': error_count,
                'total': len(import_data.get('standards', []))
            }
            
            logger.info(f"Import completed: {result}")
            return result
        
        except Exception as e:
            logger.error(f"Failed to import standards: {e}")
            raise


# 全局清洁标准管理器实例
cleanliness_standards_manager = CleanlinessStandardsManager()